#ifndef ICONFILETOOLS_H
#define ICONFILETOOLS_H

#include<QIcon>
#include<QDebug>
#include<QString>
#include<QPainter>
#include<QFileInfo>
#include<QSvgRenderer>
#include<QMimeDatabase>
#include<QDomElement>

enum class IconFileType //输入图标文件的类型
{
    svg,   // mimeType = "image/svg+xml"
    png,   // mimeType = "image/png"
    jpeg,  // mimeType = "image/jpeg"
    other
};

//基于MimeDatabase检测图标文件的类型
inline IconFileType probeIconMimeType(const QString& filePath)
{
    QMimeDatabase db;
    QFile file(filePath);
    if (file.open(QIODevice::ReadOnly))
    {
        QByteArray data = file.read(1024); // 读取文件的前1024个字节用于MIME类型检测
        file.close();
        QString mimeStr = db.mimeTypeForData(data).name();
        if("image/svg+xml" == mimeStr)
        {
            return IconFileType::svg;
        }
        else if("image/png" == mimeStr)
        {
            return IconFileType::png;
        }
        else if("image/jpeg" == mimeStr)
        {
            return IconFileType::jpeg;
        }
    }
    return IconFileType::other;
}

inline QPixmap svgToPixmap(const QString& filepath,const QSize& size)
{
    QSvgRenderer renderer(filepath);
    if(renderer.isValid())
    {
        QPixmap pixmap(size);
        pixmap.fill(Qt::transparent);

        QPainter painter(&pixmap);
        renderer.render(&painter, QRectF(QPointF(0, 0), QSizeF(size)));
        return pixmap;
    }
    return QPixmap();
}




inline QString getAbsPath(const QString& filepath)
{
    QFileInfo fi(filepath);
    return fi.absoluteFilePath();
}

/*
 * 用于数据存储的key
*/
inline int MSKey(QIcon::Mode mode, QIcon::State state)//Mode:0~3,State:0~1
{
    qDebug() << "[inline int MSKey]: 生成 MS key = "  << (mode*2+state);
    return mode*2 + state;
}

/*
    生成用于QPixmapCache缓存(key,pixmap)
    将 QSize 的宽度、高度，以及 mode 和 state 的整型值拼接成字符串，作为key

    图片路径需要作为key的一部分么？
    想了下，应该不需要，因为当前所有内容都是基于同一个QIcon对象的，那么add的图片只有2种情况：

    1、QIcon对象，要么设置一张svg，
    2、要么根据不同mode，state设置多张svg。这种情况下，不同mode，state对应的图片肯定不一样，如果是一样也没关系，自然可以根据mode，state找到同一张图

    但这样的话，必须在QIcon对象销毁的时候执行 QPixmapCache::clear
*/
inline QString pixmapCacheKey(const QString& svgPath,const QSize& size, QIcon::Mode mode, QIcon::State state)
{
    return QStringLiteral("pixmapCache_key_%1_%2_%3_%4_%5")
//            .arg(qHash(svgPath))
            .arg(svgPath)
            .arg(size.width())
            .arg(size.height())
            .arg(static_cast<int>(mode))
            .arg(static_cast<int>(state));
}
//额外写一个重载吧
inline QString pixmapCacheKey(const QSize& size, QIcon::Mode mode, QIcon::State state)
{
    return QStringLiteral("pixmapCache_key_%1_%2_%3_%4")
            .arg(size.width())
            .arg(size.height())
            .arg(static_cast<int>(mode))
            .arg(static_cast<int>(state));
}


/**
 * 基于DOM操作, 修改svg的颜色
 * elem:DOM树的一个元素句柄   strtagname：标签名  strattr:属性名    strattrval:属性值
 */
inline void setElemAttr(QDomElement& elem,QString targetTag,QString attr,QString attrValue)
{
    qDebug() << "setElemAttr: 当前 elem.tagName = " << elem.tagName();
    qDebug() << "                               elem.Attr = " << attr;
    //找到了目标标签，则直接修改属性对应的属性值（这个场景下，属性值就是我们需要改变的目标颜色）
    if(elem.tagName() == targetTag)
    {
        elem.setAttribute(attr,attrValue);
    }
    for(int i=0;i<elem.childNodes().count();i++)
    {
        if(!elem.childNodes().at(i).isElement())
        {
            continue;
        }
        QDomElement childElem = elem.childNodes().at(i).toElement();
        setElemAttr(childElem,targetTag,attr,attrValue);
    }
}

//RGB颜色转换为16进制
//因为svg的xml中描述颜色是用 #D32520 这种16进制的表达，而Qt中一般用 QColor
inline QString rgb2HexStr(const QColor& color)
{
    QString hexStr;
    QString redStr = QString::number(color.red(),16).rightJustified(2,'0');
    QString greenStr = QString::number(color.green(),16).rightJustified(2,'0');
    QString blueStr = QString::number(color.blue(),16).rightJustified(2,'0');
    hexStr.append("#").append(redStr).append(greenStr).append(blueStr);
    return hexStr;
//    return color.name(QColor::HexRgb);//Qt有处理这个的API
}

//把一张svg图片渲染为指定颜色，并转化为一个QPimxmap，并基于此生成一个QIcon返回
inline QIcon loadSvgAsIcon(const QString& svgPath,const QSize& targetPixmapIconSize,const QColor& targetColor)
{
    //加载该svg，得到byteArray数据，基于该byteArray构造QDomDocument，基于该DomDocument获取QDomElement，修改QDomElement
    QFile file(svgPath);
    file.open(QIODevice::ReadOnly);
    QByteArray bytes = file.readAll();

    QDomDocument document;
    document.setContent(bytes);
    file.close();

    QDomElement rootElem = document.documentElement();
    setElemAttr(rootElem,"path","fill",rgb2HexStr(targetColor));

    //将修改完毕的QDomElement，用于QSvgRenderer渲染
    QSvgRenderer renderer(document.toByteArray());
    if(!renderer.isValid())
    {
        return QIcon();
    }
    //转化为pixmap，作为QIcon返回
    QPixmap pm(targetPixmapIconSize);
    qDebug() << "pm.size = " << pm.size();
    pm.fill(Qt::transparent);
    QPainter painter(&pm);
    renderer.render(&painter);

    return QIcon(pm);
}



#endif
